/*
 * ServerConnection.cpp
 *
 *  Created on: 08-01-2011
 *      Author: Michal Lisicki
 */

#include "ServerConnection.h"

#include <stdio.h>
#include <cstring>
#include <stdlib.h>

using namespace Network;

ServerConnection::ServerConnection() { }
ServerConnection::~ServerConnection() { }

bool ServerConnection::init(std::string host, int port) {
	host_ = host; port_ = port; state_ = NOT_CONNECTED;

#ifdef _WIN32
    WSADATA WsaData;
    WSAStartup(MAKEWORD(2,2), &WsaData);
#endif

    sock_ = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock_==-1) {
		return false;
	}
	target_.sin_family = AF_INET;
	target_.sin_addr.s_addr = inet_addr((char*)host_.c_str());
	target_.sin_port = htons(port_);

/*
// Ustawienie typu nieblokujacego przede wszystkim ze wzgledu
// na organizacje kodu czytania z gniazda
#ifdef _WIN32
	DWORD nonBlocking = 1;
	if ( ioctlsocket(sock_, FIONBIO, &nonBlocking ) != 0 ) {
		close();
		return false;
	}
#else
	int nonBlocking = 1;
	if ( fcntl(sock_, F_SETFL, O_NONBLOCK, nonBlocking ) == -1 ) {
		close();
		return false;
	}
#endif
*/
	return true;
}

bool ServerConnection::connect() {
	if(state_==NOT_CONNECTED) {
		state_ = CONNECTING;
//		do {
			Packet sPacket(JOIN);
			sendPacket(sPacket);
			Packet rPacket = receivePacket();
			if(rPacket.length_>0 && rPacket.type_==JOIN_ACC) {
				setPort(atoi(rPacket.msg_.c_str()));
				state_=CONFIGURING;
				return true;
			} else if(rPacket.length_>0 && rPacket.type_==JOIN_NAC) {
				state_=NOT_CONNECTED;
				return false;
			}
			// elseif connection timeout
//			wait(DELTA_TIME);
//		} while(state_==CONNECTING);
	}
	return true;
}

void ServerConnection::write() {
	if(!sout_.str().empty() && !state_==NOT_CONNECTED) {
// TODO sprawdzanie typu struktury w strumieniu. Mozliwe struktury:
//		behaviour, facing, behaviour_and_facing
// XXX: moze to zbedne? Generalnie komenda przy serializacji wstawia do
//		strumienia swoj typ; moze wiec nie trzeba tego sprawdzac.
//		Jezeli trzeba, to wyciagnac mozna latwo:
//		MsgType mtype; sout_ >> mtype;
// YYY: aha. nie zauwaylem jak bardzo rozwinieta jest Twoja serializacja
//		w takim razie chyba faktycznie to zbedne


		Packet packet(SET_BEHAVIOUR, sout_.str().c_str());
		sendPacket(packet);
		sout_.str("");
	}
}

void ServerConnection::read() {

}

void ServerConnection::close() {
#ifdef _WIN32
	closesocket(sock_);
	WSACleanup();
#else
	close(sock_);
#endif
	state_=NOT_CONNECTED;
}

void reset() {
//	state = NOT_CONNECTED;
//	timeoutAccumulator = 0.0f;
//	address = Address();
}

std::istringstream& ServerConnection::getInputString() {
	return sin_;
}

std::ostringstream& ServerConnection::getOutputStream() {
	return sout_;
}

int ServerConnection::getPort() {
	return port_;
}

void ServerConnection::setPort(int port) {
	port_ = port;
	target_.sin_port = htons(port_);
}

bool ServerConnection::isClosed() {
	return false;
}
